#include <stdint.h>
#include <string.h>
#include "jpegConvert.h"
#include "jpeglib.h"
#include "jerror.h"
#include "JpegTable.h"

int jpeg_2_rgba(char *jpeg_buffer, int jpeg_buffer_len, char *rgba_buffer)
{
	struct jpeg_decompress_struct cinfo;
	struct jpeg_error_mgr jerr;
	unsigned char *buffer;
    int BufferLen = 0;
	
	//JpegCacheLen = 64*1024;
    JpegCacheLen = 512*1024;
	//JpegCacheLen = 1*1024*1024;
    //JpegCacheLen = 4*1024*1024;
    JpegCacheUsed = 0;
    pJpegCacheRam = (char *)JpegCacheRAM;
	
	cinfo.err = jpeg_std_error(&jerr);
	jpeg_create_decompress(&cinfo);

	//printf("inBufferLength = %d\n", jpeg_buffer_len);

	//jpeg_stdio_src(&cinfo, infile);
    //从内存读取
    jpeg_mem_src(&cinfo, (unsigned char *)jpeg_buffer, jpeg_buffer_len);

	jpeg_read_header(&cinfo, TRUE);
    //cinfo.out_color_space = JCS_EXT_RGBA; 
    cinfo.out_color_space = JCS_EXT_BGRA; 

	jpeg_start_decompress(&cinfo);
	BufferLen = cinfo.output_width * cinfo.output_components;
	/*buffer = malloc(BufferLen);
    if (NULL == buffer)
    {
        return -1;
    }*/

	for (int i = 0; i < cinfo.output_height; i++)
	{
#if 0
		(void) jpeg_read_scanlines(&cinfo, &buffer, 1);
        memcpy(rgba_buffer + i * cinfo.output_width * cinfo.output_components, buffer, cinfo.output_width * cinfo.output_components);
#else
		buffer = (unsigned char *)(rgba_buffer + i * cinfo.output_width * cinfo.output_components);
		(void)jpeg_read_scanlines(&cinfo, &buffer, 1);
#endif		
	}

    //free(buffer);
    buffer = NULL;

	jpeg_finish_decompress(&cinfo);
	jpeg_destroy_decompress(&cinfo);

	return 0;
}


#if 1
// int jpeg_to_rgba(char *jpeg_buffer, int jpeg_buffer_len, char *rgba_buffer)
// {
// 	struct jpeg_decompress_struct cinfo;
// 	struct jpeg_error_mgr jerr;
// 	unsigned char *buffer;
//     int BufferLen = 0;

//     if((NULL == jpeg_buffer) || (0 == jpeg_buffer_len))
//     {
//         printf("jpeg_to_rgba input illegal! \n");
//         return -1;
//     }

//     if((0xFF != jpeg_buffer[0]) || (0xD8 != jpeg_buffer[1])){
//         printf("jpeg_to_rgba input pic not a jpg file! \n");
//         return -1;
//     }

// 	cinfo.err = jpeg_std_error(&jerr);
// 	jpeg_create_decompress(&cinfo);

// 	printf("inBufferLength = %d\n", jpeg_buffer_len);

// 	//jpeg_stdio_src(&cinfo, infile);
//     //从内存读取
//     jpeg_mem_src(&cinfo, jpeg_buffer, jpeg_buffer_len);

// 	jpeg_read_header(&cinfo, TRUE);
//     //cinfo.out_color_space = JCS_EXT_RGBA; 
//     cinfo.out_color_space = JCS_EXT_BGRA; 

// 	jpeg_start_decompress(&cinfo);
// 	BufferLen = cinfo.output_width * cinfo.output_components;
// 	buffer = malloc(BufferLen);
//     if (NULL == buffer)
//     {
//         return -1;
//     }

// 	for (int i = 0; i < cinfo.output_height; i++)
// 	{
// 		(void) jpeg_read_scanlines(&cinfo, &buffer, 1);
//         memcpy(rgba_buffer + i * cinfo.output_width * cinfo.output_components,
//                 buffer, cinfo.output_width * cinfo.output_components);
// 	}

//     free(buffer);
//     buffer = NULL;

// 	jpeg_finish_decompress(&cinfo);
// 	jpeg_destroy_decompress(&cinfo);

// 	return 0;
// }

void rgba_to_jpeg(unsigned char *imageData,
                    unsigned char **compressedBuffer,
                    int imageWidth,
                    int imageHeight,
                    int channels,
                    unsigned long *outSize)
{
    struct jpeg_compress_struct cinfo;
    struct jpeg_error_mgr jerr;
    unsigned char* inImageBuffer=imageData;
    JSAMPROW row_pointer[1];
    int row_stride;
    
	//JpegCacheLen = 64*1024;
    JpegCacheLen = 512*1024;
	//JpegCacheLen = 1*1024*1024;
    //JpegCacheLen = 4*1024*1024;
    JpegCacheUsed = 0;
    pJpegCacheRam = (char *)JpegCacheRAM;
 
    cinfo.err=jpeg_std_error(&jerr);
    jpeg_create_compress(&cinfo);
    jpeg_mem_dest(&cinfo,compressedBuffer,outSize);
    cinfo.image_width=imageWidth;
    cinfo.image_height=imageHeight;
    cinfo.input_components=channels;
    cinfo.in_color_space=JCS_EXT_BGRA;
    jpeg_set_defaults(&cinfo);
    jpeg_set_quality(&cinfo, 95, TRUE);
    jpeg_start_compress(&cinfo,TRUE);
    row_stride=imageWidth * channels;
    while(cinfo.next_scanline<cinfo.image_height)
   {
     row_pointer[0]=&inImageBuffer[cinfo.next_scanline*row_stride];
     (void)jpeg_write_scanlines(&cinfo,row_pointer,1);
   }
   jpeg_finish_compress(&cinfo);
   jpeg_destroy_compress(&cinfo);
   return;
}

void ir_to_jpeg(unsigned char *imageData,
                    unsigned char **compressedBuffer,
                    int imageWidth,
                    int imageHeight,
                    int channels,
                    unsigned long *outSize)
{
    struct jpeg_compress_struct cinfo;
    struct jpeg_error_mgr jerr;
    unsigned char* inImageBuffer=imageData;
    JSAMPROW row_pointer[1];
    int row_stride;
    
	JpegCacheLen = 64*1024;
    //JpegCacheLen = 512*1024;
	//JpegCacheLen = 1*1024*1024;
    //JpegCacheLen = 4*1024*1024;
    JpegCacheUsed = 0;
    pJpegCacheRam = (char *)JpegCacheRAM;
 
    cinfo.err=jpeg_std_error(&jerr);
    jpeg_create_compress(&cinfo);
    jpeg_mem_dest(&cinfo,compressedBuffer,outSize);
    cinfo.image_width=imageWidth;
    cinfo.image_height=imageHeight;
    cinfo.input_components=channels;
    cinfo.in_color_space=JCS_GRAYSCALE;
    jpeg_set_defaults(&cinfo);
    jpeg_set_quality(&cinfo, 95, TRUE);
    jpeg_start_compress(&cinfo,TRUE);
    row_stride=imageWidth * channels;
    while(cinfo.next_scanline<cinfo.image_height)
   {
     row_pointer[0]=&inImageBuffer[cinfo.next_scanline*row_stride];
     (void)jpeg_write_scanlines(&cinfo,row_pointer,1);
   }
   jpeg_finish_compress(&cinfo);
   jpeg_destroy_compress(&cinfo);
   return;
}

int jpeg_to_ir(char *jpeg_buffer, int jpeg_buffer_len, char *ir_buffer)
{
    struct jpeg_decompress_struct cinfo;
    struct jpeg_error_mgr jerr;
    unsigned char *buffer;
    int BufferLen = 0;
    
	JpegCacheLen = 64*1024;
    //JpegCacheLen = 512*1024;
	//JpegCacheLen = 1*1024*1024;
    //JpegCacheLen = 4*1024*1024;
    JpegCacheUsed = 0;
    pJpegCacheRam = (char *)JpegCacheRAM;

    if((NULL == jpeg_buffer) || (0 == jpeg_buffer_len))
    {
        printf("jpeg_to_ir input illegal! \n");
        return -1;
    }

    cinfo.err = jpeg_std_error(&jerr);
    jpeg_create_decompress(&cinfo);

    //printf("inBufferLength = %d\n", jpeg_buffer_len);

    //jpeg_stdio_src(&cinfo, infile);
    //从内存读取
    jpeg_mem_src(&cinfo, (unsigned char *)jpeg_buffer, jpeg_buffer_len);

    jpeg_read_header(&cinfo, TRUE);
    //cinfo.out_color_space = JCS_EXT_RGBA; 
    cinfo.out_color_space = JCS_GRAYSCALE; 

    jpeg_start_decompress(&cinfo);
    BufferLen = cinfo.output_width * cinfo.output_components;
    buffer = malloc(BufferLen);
    if (NULL == buffer)
    {
        return -1;
    }

    for (int i = 0; i < cinfo.output_height; i++)
    {
        (void) jpeg_read_scanlines(&cinfo, &buffer, 1);
        memcpy(ir_buffer + i * cinfo.output_width * cinfo.output_components,
                buffer, cinfo.output_width * cinfo.output_components);
    }

    free(buffer);
    buffer = NULL;

    jpeg_finish_decompress(&cinfo);
    jpeg_destroy_decompress(&cinfo);

    return 0;
}

#if 0
int jpeg_to_raw(char *jpeg_buffer, int jpeg_buffer_len, char *rgba_buffer, int *width, int *height, ext_pic_type_e type)
{
	struct jpeg_decompress_struct cinfo;
	struct jpeg_error_mgr jerr;
	unsigned char *buffer;
    int BufferLen = 0;

	//JpegCacheLen = 64*1024;
    JpegCacheLen = 512*1024;
	//JpegCacheLen = 1*1024*1024;
    //JpegCacheLen = 4*1024*1024;
    JpegCacheUsed = 0;
    pJpegCacheRam = (char *)JpegCacheRAM;

    if((NULL == jpeg_buffer) || (0 == jpeg_buffer_len))
    {
        printf("jpeg_to_raw input illegal! \n");
        return -1;
    }

    if((0xFF != jpeg_buffer[0]) || (0xD8 != jpeg_buffer[1])){
        printf("jpeg_to_raw input pic not a jpg file! \n");
        return -1;
    }

	cinfo.err = jpeg_std_error(&jerr);
	jpeg_create_decompress(&cinfo);

	//printf("inBufferLength = %d\n", jpeg_buffer_len);

	//jpeg_stdio_src(&cinfo, infile);
    //从内存读取
    jpeg_mem_src(&cinfo, jpeg_buffer, jpeg_buffer_len);

	jpeg_read_header(&cinfo, TRUE);

    if( (cinfo.image_width*cinfo.image_height) > (1280*720) )
    {
        printf("srcImg > 720p, please make it smaller!!! \n");  
        return -1;
    }    

    
    if(EXT_RAW == type)
    {
        cinfo.out_color_space = JCS_GRAYSCALE; 
    }
    else if(EXT_RGBA == type)
    {
        //cinfo.out_color_space = JCS_EXT_RGBA; 
        cinfo.out_color_space = JCS_EXT_BGRA;  //now
    }
    else
    {
        /* code */
        cinfo.out_color_space = JCS_EXT_BGRA;  //now
    }
    
	jpeg_start_decompress(&cinfo);

    if((width != NULL) && (height != NULL)) 
    {
        *width = cinfo.output_width;
        *height = cinfo.output_height;
    }

	BufferLen = cinfo.output_width * cinfo.output_components;
	buffer = malloc(BufferLen);
    if (NULL == buffer)
    {
        return -1;
    }

	for (int i = 0; i < cinfo.output_height; i++)
	{
		(void) jpeg_read_scanlines(&cinfo, &buffer, 1);
        memcpy(rgba_buffer + i * cinfo.output_width * cinfo.output_components,
                buffer, cinfo.output_width * cinfo.output_components);
	}

    free(buffer);
    buffer = NULL;

	jpeg_finish_decompress(&cinfo);
	jpeg_destroy_decompress(&cinfo);

	return 0;
}
#endif

// const char g_acJpegArray[50000] = {0};
// int g_acJpegArrayLen = 43785;
// int jpeg_test(void)
// {
//     char *rgba_buffer = NULL;
//     int ret = 0;
//     int lRgbaBufferLen = 0;

// 	lRgbaBufferLen = 360 * 640 * 4;
// 	rgba_buffer = malloc(lRgbaBufferLen);
//     if (NULL == rgba_buffer)
//     {
//         return -1;
//     }

//     ret = jpeg_to_rgba(g_acJpegArray, g_acJpegArrayLen, rgba_buffer);

//     if (ret != 0)
//     {
//         free(rgba_buffer);
//         return -1;
//     }

//     while(1);

//     free(rgba_buffer);

//     return 0;
// }

#endif
